package com.csu.common.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.log4j.Logger;
import org.springframework.util.ReflectionUtils;

public class BeanUtil
{

    private static Logger logger = Logger.getLogger(BeanUtil.class);
    private static BeanUtilsBean beanUtilsBean = BeanUtilsBean.getInstance();

    /**
     * 拷贝一个bean中的非空属性于另一个bean中
     * 
     * @param dest
     * @param orig
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public static void copyNotNullProperties(Object dest, Object orig)
    {

        // Validate existence of the specified beans
        if (dest == null)
        {
            logger.error("No destination bean specified");
            return;
        }
        if (orig == null)
        {
            logger.error("No origin bean specified");
            return;
        }

        try
        {
            // Copy the properties, converting as necessary
            if (orig instanceof DynaBean)
            {
                DynaProperty[] origDescriptors = ((DynaBean) orig).getDynaClass().getDynaProperties();
                for (int i = 0; i < origDescriptors.length; i++)
                {
                    String name = origDescriptors[i].getName();
                    if (beanUtilsBean.getPropertyUtils().isReadable(orig, name) && beanUtilsBean.getPropertyUtils().isWriteable(dest, name))
                    {
                        Object value = ((DynaBean) orig).get(name);
                        if (value != null)
                        {
                            beanUtilsBean.copyProperty(dest, name, value);
                        }
                    }
                }
            }
            else if (orig instanceof Map)
            {
                Iterator<?> entries = ((Map<?, ?>) orig).entrySet().iterator();
                while (entries.hasNext())
                {
                    @SuppressWarnings("rawtypes")
                    Map.Entry entry = (Map.Entry) entries.next();
                    String name = (String) entry.getKey();
                    if (beanUtilsBean.getPropertyUtils().isWriteable(dest, name))
                    {
                        Object value = entry.getValue();
                        if (value != null)
                        {
                            beanUtilsBean.copyProperty(dest, name, value);
                        }
                    }
                }
            }
            else
            /* if (orig is a standard JavaBean) */ {
                PropertyDescriptor[] origDescriptors = beanUtilsBean.getPropertyUtils().getPropertyDescriptors(orig);
                for (int i = 0; i < origDescriptors.length; i++)
                {
                    String name = origDescriptors[i].getName();
                    if ("class".equals(name))
                    {
                        continue; // No point in trying to set an object's class
                    }
                    if (beanUtilsBean.getPropertyUtils().isReadable(orig, name) && beanUtilsBean.getPropertyUtils().isWriteable(dest, name))
                    {
                        try
                        {
                            Object value = beanUtilsBean.getPropertyUtils().getSimpleProperty(orig, name);
                            if (value != null)
                            {
                                beanUtilsBean.copyProperty(dest, name, value);
                            }
                        }
                        catch (NoSuchMethodException e)
                        {
                            ExceptionUtil.log(e, logger);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            ReflectionUtils.handleReflectionException(ex);
        }

    }

}
